package org.dallasrowing.logbook.ui.controller;

import java.util.Date;
import java.util.List;

import org.dallasrowing.logbook.ui.view.LogBookWindow;
import org.dallasrowing.logbook.ui.view.ReportNewDamageWindow;
import org.dallasrowing.model.Boat;
import org.dallasrowing.model.DamageEntry;
import org.dallasrowing.model.dao.BoatsDAO;
import org.dallasrowing.model.dao.DAOException;
import org.dallasrowing.model.dao.DamagesDAO;

public class ReportNewDamageControllerImpl implements ReportNewDamageController {

	private ReportNewDamageWindow reportNewDamageWindow;
	private LogBookWindow mainWindow;
	private BoatsDAO boatsDao;
	private DamagesDAO damagesDao;
	
	protected List<DamageEntry> currentDamages;
	protected List<Boat> boatsResult;
	protected DamageEntry selectedReport = null;
	private Date currentTimestamp = new Date();

	public ReportNewDamageControllerImpl(LogBookWindow mainWindow,
			BoatsDAO boatsDao, DamagesDAO damagesDAO) {
		this.mainWindow = mainWindow;
		this.boatsDao = boatsDao;
		this.damagesDao = damagesDAO;
	}

	public void newReportNewDamageWindow(
			ReportNewDamageWindow openReportNewDamageWindow) {
		this.reportNewDamageWindow = openReportNewDamageWindow;
		
	}

	public void openReportNewDamageWindow() {
		registerListeners();
		populateWindowData();
	}

	private void registerListeners() {
		reportNewDamageWindow.setCreateNewEntryListener(new Runnable() {
			public void run() {
				startCreateNewReport();
			}
		});
		reportNewDamageWindow.setSelectDamageListener(new Runnable() {
			
			public void run() {
				currentDamageSelected();
			}
			
		});
		reportNewDamageWindow.setSaveButtonListener(new Runnable() {
			
			public void run() {
				saveDamageEntry();
			}
			
		});
	}

	protected void saveDamageEntry() {
		try {
			if (isNewReport())
			{
				saveNewDamageEntryInDao();
			}
			else
			{
				closeDamageReportInDao();
			}
		} catch (DAOException e) {
			mainWindow.showError(e);
		}
		reportNewDamageWindow.closeWindow();
	}

	private void closeDamageReportInDao() throws DAOException {
		boolean damageRepaired = reportNewDamageWindow.getDamageRepairedFlag();
		if (damageRepaired)
		{
			selectedReport.setDamageCloseDate(getTimeStamp());
			damagesDao.closeDamageEntry(selectedReport);
		}
	}

	private boolean isNewReport() {
		return selectedReport == null;
	}

	private void saveNewDamageEntryInDao() throws DAOException {
		DamageEntry damageEntry = reportNewDamageWindow.getDamageData();
		damagesDao.addDamageEntry(damageEntry);
	}

	protected void currentDamageSelected() {
		int selectedIndex = reportNewDamageWindow.getSelectedExistingDamage();
		DamageEntry damageEntry = currentDamages.get(selectedIndex);
		int boatIndex = findBoatInList(damageEntry.getBoat(), boatsResult );
		reportNewDamageWindow.populateCurrentDamage(damageEntry, boatIndex);
		selectedReport = damageEntry;
	}

	private int findBoatInList(Boat boat, List<Boat> boatsResult) {
		for (int i = 0; i < boatsResult.size(); i++)
		{
			if (boatsResult.get(i).getId() == boat.getId())
			{
				return i;
			}
		}
		return -1;
	}

	protected void startCreateNewReport() {
		reportNewDamageWindow.setCreateEntryDate(getTimeStamp());
		reportNewDamageWindow.enableAndWipeAllTextFields();
		selectedReport = null;
	}

	private void populateWindowData() {
		try {
			boatsResult = boatsDao.allBoats(false);
			reportNewDamageWindow.populateBoats(boatsResult);
			populateCurrentDamages();
		} catch (DAOException e) {
			mainWindow.showError(e);
		}
	}

	private void populateCurrentDamages() throws DAOException {
		currentDamages = damagesDao.allDamages();
		
		reportNewDamageWindow.setDamagesList(currentDamages);
	}

	Date getTimeStamp() {
		return currentTimestamp ;
	}

}
